This Week In Security: Forksquatting, RustDesk, And M&Ms

Github is struggling to keep up with a malware campaign that’s a new twist on typosquatting. The play is straightforward: Clone popular repositories, add malware, and advertise the forks as the original. Some developers mistake the forks for the real projects, and unintentionally run the malware. The obvious naming choice is forksquatting, but the researchers at apiiro went with the safer name of “Repo Confusion”.

The campaign is automated, and GitHub is aware of it, with the vast majority of these malicious repositories getting removed right away. For whatever reason, the GitHub algorithm isn’t catching all of the new repos. The current campaign appears to publishing millions of forks, using code from over 100,000 legitimate projects. It’s beginning to seem that the squatting family of attacks are here to stay.

RustDesk and Odd Certificates

The RustDesk remote access software is interesting, as it’s open source, allows self-hosting, and written in Rust. I’ve had exploring RustDesk as a todo item for a long time, but a bit of concerning drama has just finished playing out. A user pointed out back in November that a test root certificate was installed as part of the RustDesk installation. That root cert is self-signed with SHA1. There is also concern that the RustDesk binaries are signed with a different certificate.

There have been new events since then. First, there was a Hacker News thread about the issue earlier this month. The next day, CVE-2024-25140 was registered with NIST, ranking an insane CVE 9.8 CVSS. Let’s cut through some FUD and talk about what’s really going on.

Continue reading “This Week In Security: Forksquatting, RustDesk, And M&Ms”

This Week In Security: Filename Not Sanitized, MonikerLink, And Snap Attack!

Reading through a vulnerability report about ClamAV, I came across a phrase that filled me with dread: “The file name is not sanitized”. It’s a feature, VirusEvent, that can be enabled in the ClamnAV config. And that configuration includes a string formatting function, where the string includes %v and %s, which gets replaced with a detected virus name and the file name from the email. And now you see the problem, I hope: The filename is attacker supplied input.

Where this really gets out of hand is what ClamAV does with this string. execle("/bin/sh", "sh", "-c", buffer_cmd, NULL, env). So let’s talk defensive program design for a minute. When it comes to running a secondary command, there are two general options, system() and the exec*() family of system calls. system() is very simple to use. It pauses execution of the main process and asks the operating system to run a string, just as if the user had typed that command into the shell. While this is very convenient to use, there is a security problem if any of that command string is user-supplied. All it takes is a semicolon or ampersand to break assumptions and inject a command.

To the rescue comes exec(). It’s a bit more complicated to use, requiring the programmer to manually call fork() and wait(). But it’s not running the command via the shell. exec() executes a program directly, totally eliminating the potential for command injection! Except… oops.

Yeah, exec() and related calls don’t offer any security protections when you use them to execute /bin/sh. I suspect the code was written this way to allow running a script without specifying /bin/sh in the config. The official fix was to disable the filename format character, and instead supply it as an environment variable. That certainly works, and that fix is available in 1.0.5, 1.2.2, and 1.3.0.

The real danger here is that we have another case where some hardware appliance manufacturer has used ClamAV for email filtering, and uses this configuration by default. That’s how we get orders from CISA to unplug your hardware, because it’s already compromised. Continue reading “This Week In Security: Filename Not Sanitized, MonikerLink, And Snap Attack!”

Zerowriter Promises Zero Distractions While Writing

As great as full-blown desktop computers may be for web surfing, gaming, and what have you, they are theaters of distraction when it comes time to write. And while there are machines out there purpose-built for writing, the price tags run awfully high for what they are, which is essentially a microprocessor handling a keyboard and an E-ink display.

So, why not build one yourself, then? That’s the idea behind the Zerowriter, which, as you may have guessed, is based on the Raspberry Pi Zero. The Zero 2 W to be exact: [zerowriter]  says that the extra power over the original Zero is quite useful.

In addition, there’s a 4.2″ Waveshare E-ink display and the Vortex Core 40% keyboard inside the 3D-printed enclosure. The design is based on the Penkesu computer, although in the Zerowriter, the Pi sits behind the screen instead of underneath the keyboard. [zerowriter] built an application on top of the Waveshare demo program that’s easy to use and modify.

The price tag for this build comes in around $200, which is a fraction of similar commercial products. Most of the cost is in this particular keyboard, although 40%s are, broadly speaking, not cheap. We would love to see someone make a keyboard for this.

Looking to make something a bit bigger? Be sure to check out the MUSE.

The X Macro: A Historic Preprocessor Hack

If we told you that a C preprocessor hack dated back to 1968, you’d be within your rights to remind us that C didn’t exist in 1968. However, assemblers with preprocessors did, and where there is a preprocessor, there is an opportunity to do clever things. One of those things is the so-called X macro, which saw a lot of use in DEC System 10 code but probably dates back even earlier. You can still use it today if you like, even though there are, of course, other arguably better ways to get the same result. However, the X macro can be very efficient, and you may well run into it in some code, too.

Background

Preprocessing used to be a staple of programming. The idea is that code is manipulated purely at the text level before it is compiled. These days, languages with a preprocessor usually handle it as part of the compiler, but you can also use an external preprocessor like m4 for more sophisticated uses.

Modern languages tend to provide other ways to accomplish many of the tasks handled by the preprocessor. For example, if you have a constant you want to set at compile time, you could say:

int X = 32;
y = X;

But then you’ve created a real variable along with the overhead that might entail. A smart compiler might optimize it away for you, but you can be sure by writing:

#define X 32
y = X;

A modern compiler would prefer you to write:

const int X=32;
y = X;

But there are still some common uses for macros, like including header files. You can also make more sophisticated macros with arguments so you don’t incur a function call penalty, although modern usage would be to mark those functions as inline.

The Problem

Which brings us to the X macro. With all great hacks, there is first a problem to solve. Imagine you have a bunch of electronic parts you want to deal with in your code. You don’t want a database, and you don’t want to carry a bunch of strings around, so you define an enumerated type:

Continue reading “The X Macro: A Historic Preprocessor Hack”

Linux Fu: The Shell Forth Programmers Will Love

One of the most powerful features of Unix and Linux is that using traditional command line tools, everything is a stream of bytes. Granted, modern software has blurred this a bit, but at the command line, everything is text with certain loose conventions about what separates fields and records. This lets you do things like take a directory listing, sort it, remove the duplicates, and compare it to another directory listing. But what if the shell understood more data types other than streams? You might argue it would make some things better and some things worse, but you don’t have to guess, you can install cosh, a shell that provides tools to produce and work with structured data types.

The system is written with Rust, so you will need Rust setup to compile it. For most distributions, that’s just a package install (rust-all in Ubuntu-like distros, for example). Once you have it running, you’ll have a few new things to learn compared to other shells you’ve used. Continue reading “Linux Fu: The Shell Forth Programmers Will Love”

This Week In Security: Git Deep Dive, Mailchimp, And SPF

First up, git has been audited. This was an effort sponsored by the Open Source Technology Improvement Fund (OSTIF), a non-profit working to improve the security of Open Source projects. The audit itself was done by researchers from X41 and GitLab, and two critical vulnerabilities were found, both caused by the same bad coding habit — using an int to hold buffer lengths.

On modern systems, a size_t is always unsigned, and the same bit length as the architecture bit-width. This is the proper data type for string and buffer lengths, as it is guaranteed not to overflow when handling lengths up to the maximum addressable memory on the system. On the other hand, an int is usually four bytes long and signed, with a maximum value of 2^31-1, or 2147483647 — about 2 GB. A big buffer, but not an unheard amount of data. Throw something that large at git, and it will break in unexpected ways.

Our first example is CVE-2022-23521, an out of bounds write caused by an int overflowing to negative. A .gitattributes file can be committed to a repository with a modified git client, and then checking out that repository will cause the num_attrs variable to overflow. Push the overflow all the way around to a small negative number, and git will then vastly under-allocate the attributes buffer, and write all that data past the end of the allocated buffer.

CVE-2022-41903 is another signed integer overflow, this time when a pretty print format gets abused to do something unexpected. Take a look at this block of code:

Continue reading “This Week In Security: Git Deep Dive, Mailchimp, And SPF”

Fork And Run: The Definitive Guide To Getting Started With Multiprocessing

Since the early 2000s, the CPU industry has shifted from raw clock speed to core counts. Pat Gelsinger famously took the stage in 2002 and gave the talk the industry needed, stating processors needed specialty silicon or multiple cores to reduce power requirements and spread heat. A few years later, the Core series was introduced with two or four-core configurations to compete with the AMD Athlon 64 x2.

Nowadays, we’re seeing heterogeneous chip designs with big and little cores, chiplets, and other crazy fabrication techniques that are fundamentally the same concept: spread the thermal load across multiple pieces of silicon. This writer is willing to put good money into betting that you’ll see consumer desktop machines with 32 physical cores in less than five years. It might be hard to believe, but a 2013 Intel Haswell i7 came with just four cores compared to the twenty you’ll get in an i7 today. Even an ESP32 has two cores with support in FreeRTOS for pinning tasks to different cores. With so many cores, how to even write software for that? What’s the difference between processes and threads? How does this all work in straight vanilla C98?

Continue reading “Fork And Run: The Definitive Guide To Getting Started With Multiprocessing”